package com.lonwin.mes2u8.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lonwin.mes2u8.common.MesConfig;
import com.lonwin.mes2u8.common.YonYouConfig;
import com.lonwin.mes2u8.domain.mes.MesCommonResult;
import com.lonwin.mes2u8.domain.mes.MesMaterialOutQueryResult;
import com.lonwin.mes2u8.domain.u8.*;
import com.lonwin.mes2u8.util.BaseInfoU8;
import com.lonwin.mes2u8.util.MyHttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 材料出库单相关操作
 * @author DELL
 * @Date 2023-12-18 15:06
 */
@Service
@Slf4j
public class MaterialOutAppService {

    @Resource
    private MesTokenService mesTokenService;
    @Resource
    private MesConfig mesConfig;
    @Resource
    private YonYouConfig yonYouConfig;


    /**
     * mes根据材料出库单编号查询材料出库单详情
     * @param id 材料出库单编号
     * @return 材料出库单详情
     */
    public List<MesMaterialOutQueryResult> getMesMaterialOutInfo(String id) {
        Map<String, String> mesMaterialOutQueryParamMap = Maps.newHashMapWithExpectedSize(1);
        mesMaterialOutQueryParamMap.put("sno", id);
        String mesMaterialOutQueryResultString = MyHttpClientUtil.sendPostRequest(
                mesConfig.getAddress() + mesConfig.getMaterialOutInfoUrl(),
                mesTokenService.buildTokenHeader(),
                JSONObject.toJSONString(mesMaterialOutQueryParamMap),
                MyHttpClientUtil::handleJsonResponse
        );

        MesCommonResult<List<MesMaterialOutQueryResult>> commonResult = JSONObject.parseObject(mesMaterialOutQueryResultString, new TypeReference<MesCommonResult<List<MesMaterialOutQueryResult>>>() {}.getType());

        if(Objects.nonNull(commonResult) && commonResult.isSuccess() && !commonResult.getResult().isEmpty()) {
            List<MesMaterialOutQueryResult> mesMaterialOutQueryResults = Lists.newArrayList();
            for (Object object : commonResult.getResult()) {
                mesMaterialOutQueryResults.add(JSONObject.parseObject(JSONObject.toJSONString(object),MesMaterialOutQueryResult.class));
            }
            return mesMaterialOutQueryResults;
        }
        return Lists.newArrayList();
    }

    public U8MaterialOutQueryBody queryMaterailOutFromU8(String id) {
        U8CommonHeader commonHeader = U8CommonHeader.builder()
                .from_account(yonYouConfig.getFromAccount())
                .to_account(yonYouConfig.getToAccount())
                .app_key(yonYouConfig.getAppKey())
                .token(BaseInfoU8.getToken())
                .build();

        String respString = MyHttpClientUtil.sendSSLGetRequest(
                yonYouConfig.getAddress() + yonYouConfig.getMaterialOutGetUrl(),
                MyHttpClientUtil.convertGetParamByObj(commonHeader) + "&id=" + id,
                MyHttpClientUtil::handleJsonResponse
        );

        U8MaterialOutQueryResult result = JSONObject.parseObject(respString, U8MaterialOutQueryResult.class);

        if (Objects.nonNull(result) && Objects.nonNull(result.getMaterialout())) {
            U8MaterialOutQueryBody body = JSONObject.parseObject(JSONObject.toJSONString(result.getMaterialout()), U8MaterialOutQueryBody.class);
            if(Objects.isNull(body.getEntry()) || body.getEntry().isEmpty()) {
                return null;
            }
            List<U8MaterialOutQueryBodyEntry> entries = Lists.newArrayList();
            for (Object entry : body.getEntry()) {
                if(Objects.isNull(entry)) {
                    continue;
                }
                entries.add(JSONObject.parseObject(JSONObject.toJSONString(entry), U8MaterialOutQueryBodyEntry.class));
            }
            body.setEntry(entries);
            return body;
        }

        return null;
    }


    /**
     * 判断材料出库单是否未被录入
     * @param id 材料出库单编号
     * @return 判断结果
     */
    public boolean isNotExistOnU8(String id) {
        return Objects.isNull(queryMaterailOutFromU8(id));
    }

    /**
     * 向U8中添加材料出库单
     * @param u8MaterialOutAddParam 材料出库单添加参数
     * @return 是否添加成功
     */
    public U8CommonSyncResponse addMaterialOutToU8(U8MaterialOutAddParam u8MaterialOutAddParam) {
        U8CommonHeader commonHeader = U8CommonHeader.builder()
                .from_account(yonYouConfig.getFromAccount())
                .to_account(yonYouConfig.getToAccount())
                .app_key(yonYouConfig.getAppKey())
                .token(BaseInfoU8.getToken())
                .tradeid(BaseInfoU8.getTradeId())
                .build();

        String respString = MyHttpClientUtil.sendSSLPostRequest(
                yonYouConfig.getAddress() + yonYouConfig.getMaterialOutAddUrl() + "?" + MyHttpClientUtil.convertGetParamByObj(commonHeader),
                null,
                JSONObject.toJSONString(u8MaterialOutAddParam),
                MyHttpClientUtil::handleJsonResponse
        );

        U8CommonSyncResponse u8AddSyncResult = JSONObject.parseObject(respString, U8CommonSyncResponse.class);

        return u8AddSyncResult;
    }

    /**
     * 根据批次号(讨论后更改为产成品编号，新增时备注中也填产品编号）获取U8中材料出库单信息
     * @param batchCode 批次号
     * @return 材料出库单信息
     */
    public List<U8MaterialOutBatchGetInfo> getU8MaterialOutListByMesBatchCode(String batchCode) {

        U8CommonHeader commonHeader = U8CommonHeader.builder()
                .from_account(yonYouConfig.getFromAccount())
                .to_account(yonYouConfig.getToAccount())
                .app_key(yonYouConfig.getAppKey())
                .token(BaseInfoU8.getToken())
                .tradeid(BaseInfoU8.getTradeId())
                .build();

        String respString = MyHttpClientUtil.sendSSLGetRequest(
                yonYouConfig.getAddress() + yonYouConfig.getMaterialOutBatchGetUrl() + "?" + MyHttpClientUtil.convertGetParamByObj(commonHeader) + "&memory=" + batchCode,
                null,
                MyHttpClientUtil::handleJsonResponse
        );

        U8MaterialOutBatchGetResult u8AddSyncResult = JSONObject.parseObject(respString, U8MaterialOutBatchGetResult.class);

        if (Objects.isNull(u8AddSyncResult) || Objects.isNull(u8AddSyncResult.getMaterialoutlist()) || u8AddSyncResult.getMaterialoutlist().isEmpty()) {
            log.error("MaterialOutAppService.getU8MaterialOutListByMesBatchCode occur exception, return null : {}", batchCode);
            return null;
        }

        List<U8MaterialOutBatchGetInfo> materialoutlist = u8AddSyncResult.getMaterialoutlist();

        ArrayList<U8MaterialOutBatchGetInfo> result = Lists.newArrayList();
        for (Object batchGetResult : materialoutlist) {
            if (Objects.nonNull(batchGetResult)) {
                result.add(JSONObject.parseObject(JSONObject.toJSONString(batchGetResult), U8MaterialOutBatchGetInfo.class));
            }
        }

        return result;
    }

    /**
     * 将MES中按单个产品编码查询结果汇总
     * @param mesMaterialOutQueryResultList MES系统按批次号查询结果
     * @return 每个物料的使用情况 key:产品编号+分隔符+物料号 value:MaterialOutQueryResult 所有物料的总重
     */
    public List<U8MaterialOutHandlerResult> handleMesMaterialOutQueryResultOfGroup(List<MesMaterialOutQueryResult> mesMaterialOutQueryResultList) {

        if (Objects.isNull(mesMaterialOutQueryResultList) || mesMaterialOutQueryResultList.isEmpty()) {
            return Lists.newArrayList();
        }

        MesMaterialOutQueryResult first = mesMaterialOutQueryResultList.get(0);

        // 按产品编号进行分组 sponoGroup : key-产品编号 value-MesMaterialOutQueryResultList
        Map<String, List<MesMaterialOutQueryResult>> sponoGroup = mesMaterialOutQueryResultList.stream().collect(Collectors.groupingBy(MesMaterialOutQueryResult::getSpono));

        List<U8MaterialOutHandlerResult> u8MaterialOutHandlerResultList = Lists.newArrayList();
        for (Map.Entry<String, List<MesMaterialOutQueryResult>> groupEntry : sponoGroup.entrySet()) {
            // 按物料号进行分组 key-物料编号 value-MesMaterialOutQueryResultList
            Map<String, List<MesMaterialOutQueryResult>> mnoGroup = groupEntry.getValue().stream().collect(Collectors.groupingBy(MesMaterialOutQueryResult::getMno));

            List<U8MaterialOutHandlerResultInfo> resultInfoList = Lists.newArrayList();
            for (Map.Entry<String, List<MesMaterialOutQueryResult>> mnoGroupEntry : mnoGroup.entrySet()) {
                BigDecimal sumRealityBlanking = mnoGroupEntry.getValue().stream().map(MesMaterialOutQueryResult::getSumRealityBlanking).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal sumNum = mnoGroupEntry.getValue().stream().map(MesMaterialOutQueryResult::getNum).reduce(BigDecimal.ZERO, BigDecimal::add);
                MesMaterialOutQueryResult mnoFirst = mnoGroupEntry.getValue().get(0);
                U8MaterialOutHandlerResultInfo u8MaterialOutHandlerResultInfo = U8MaterialOutHandlerResultInfo.builder()
                        .mno(mnoFirst.getMno())
                        .mdes(mnoFirst.getMdes())
                        .weight(sumRealityBlanking.divide(new BigDecimal("1000"), 6, RoundingMode.HALF_UP))
                        .number(sumNum)
                        .build();
                resultInfoList.add(u8MaterialOutHandlerResultInfo);
            }

            U8MaterialOutHandlerResult u8MaterialOutHandlerResult = U8MaterialOutHandlerResult.builder()
                    .batchCode(first.getSno()).inventoryCode(first.getSpono())
                    .infoList(resultInfoList)
                    .build();

            u8MaterialOutHandlerResultList.add(u8MaterialOutHandlerResult);
        }
        return u8MaterialOutHandlerResultList;
    }

    /**
     * 根据U8中已有的数据，对每个原材料的使用情况进行统计
     * @param existU8MaterialQueryBodyList
     * @return
     */
    public List<U8MaterialOutHandlerResultInfo> handlerU8MaterialExistSumInfo(List<U8MaterialOutQueryBody> existU8MaterialQueryBodyList) {
        if (Objects.isNull(existU8MaterialQueryBodyList) || existU8MaterialQueryBodyList.isEmpty()) {
            return Lists.newArrayList();
        }

        U8MaterialOutQueryBody first = existU8MaterialQueryBodyList.get(0);

        Map<String, BigDecimal> u8MonUseNumMap = Maps.newHashMapWithExpectedSize(24);
        List<U8MaterialOutHandlerResult> u8MaterialOutHandlerResultList = Lists.newArrayList();
        List<U8MaterialOutHandlerResultInfo> infos = Lists.newArrayList();
        for (U8MaterialOutQueryBody u8MaterialOutQueryBody : existU8MaterialQueryBodyList) {

            // 对相同原料用量进行汇总
            List<U8MaterialOutQueryBodyEntry> entries = u8MaterialOutQueryBody.getEntry();
            for (U8MaterialOutQueryBodyEntry entry : entries) {
                if (!u8MonUseNumMap.containsKey(entry.getInventorycode())) {
                    u8MonUseNumMap.put(entry.getInventorycode(), BigDecimal.ZERO);
                }
                u8MonUseNumMap.put(entry.getInventorycode(), u8MonUseNumMap.get(entry.getInventorycode()).add(entry.getQuantity()));
            }

            // 转换成U8BillHandlerResult对象

            for (Map.Entry<String, BigDecimal> entry : u8MonUseNumMap.entrySet()) {
                U8MaterialOutHandlerResultInfo info = U8MaterialOutHandlerResultInfo.builder()
                       .mno(entry.getKey())
                       .weight(entry.getValue())
                       .build();
                infos.add(info);
            }
        }

        return infos;
    }
}
